package req

import (
	"errors"
	"project-info/src/lib"
	"project-info/src/service"
	"strings"

	"gorm.io/gorm")

const DataPermissionContextKey = "dataPermission"

type DataPermission struct {
	UserId  uint64   // 用户id
	RoleIds []uint64 // 角色id
}

// DataPermissionHandlerConfig 配置权限
func DataPermissionHandlerConfig() lib.MiddlewareFunc {
	return func(c *lib.GinContext) error {
		token := lib.JwtParse(c)

		roleIds, err := service.GetRoleIdsByUserId(c, token.UserId)
		if err != nil {
			c.Logger().Error(err.Error())
			return err
		}
		dp := &DataPermission{
			UserId:  token.UserId,
			RoleIds: roleIds,
		}

		c.Set(DataPermissionContextKey, dp)
		return nil
	}
}

func HandleResourceDataPermission(c *lib.GinContext, resourceTypes []int8, db *gorm.DB) (*gorm.DB, error) {
	isAdmin, err := (&service.UserService{}).IsAdmin(lib.JwtParse(c))
	// admin 直接返回
	if err != nil || isAdmin {
		return db, err
	}

	dataPermissionObj, exists := c.Get(DataPermissionContextKey)
	if !exists || dataPermissionObj == nil {
		return db, errors.New("未找到数据权限处理对象")
	}
	dataPermission, ok := dataPermissionObj.(*DataPermission)
	if !ok {
		return db, errors.New("数据权限对象出错")
	}

	return ConcatDataPermissionSql(c, resourceTypes, db, dataPermission), nil
}

func ConcatDataPermissionSql(c *lib.GinContext, resourceTypes []int8, db *gorm.DB, dataPermission *DataPermission) *gorm.DB {
	var conditions []string
	var args []interface{}
	if dataPermission.UserId != 0 {
		conditions = append(conditions, "select resource_id from resource_users where user_id = ? and resource_type in ?")
		args = append(args, dataPermission.UserId, resourceTypes)
	}

	if len(dataPermission.RoleIds) > 0 {
		conditions = append(conditions, "select resource_id from resource_roles where role_id in ? and resource_type in ?")
		args = append(args, dataPermission.RoleIds, resourceTypes)
	}
	subQuery := strings.Join(conditions, " union all ")
	db = db.Where("id in ( "+subQuery+" )", args...)
	return db
}
